﻿// -----------------------------------------------------------------------
// <copyright file="QueueController.cs" company="Abyssalsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Metal.Player.Playlist
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Reflection;
    using System.Text;
    using System.Windows.Forms;
    using System.Xml;

    /// <summary>
    /// Queue controller
    /// </summary>
    public class QueueController
    {
        #region Members

        /// <summary>Stores our view to communicate with the mask</summary>
        private static IQueueView view;

        /// <summary>The data set used to bind the list</summary>
        private static DataSet dataSet;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the QueueController class.
        /// </summary>
        /// <param name="iView">Interface to communicate with the mask</param>
        public QueueController(IQueueView iView)
        {
            view = iView;
            this.SubscribeToViewEvents();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the playlist data set
        /// </summary>
        public static DataSet ListDataSet
        {
            get
            {
                return dataSet;
            }

            set
            {
                dataSet = value;
            }
        }

        /// <summary>
        /// Gets or sets the interface to communicate with the mask
        /// </summary>
        internal static IQueueView View
        {
            get
            {
                return view;
            }

            set
            {
                view = value;
            }
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Play the next file in the playlist
        /// </summary>
        public static void PlayNext()
        {
            // Play first file from the list
            Core.Player.Playback.Instance.Open(ListDataSet.Tables[0].Rows[0][1].ToString());
            Core.Player.Playback.Instance.Play();

            // Delete first file
            ListDataSet.Tables[0].Rows[0].Delete();
            SaveCurrentPlaylist();
        }

        /// <summary>
        /// Add row to queue
        /// </summary>
        /// <param name="row">The row to add</param>
        public static void AddFileToQueue(DataGridViewRow row)
        {
            ListDataSet.Tables[0].Rows.Add(ListDataSet.Tables[0].Rows.Count + 3, row.Cells[1].Value, row.Cells[2].Value);
        }

        /// <summary>
        /// Save the current playlist
        /// </summary>
        public static void SaveCurrentPlaylist()
        {
            try
            {
                if (ListDataSet == null)
                {
                    return;
                }

                XmlWriterSettings xmlSettings = new XmlWriterSettings();
                xmlSettings.Indent = true;
                xmlSettings.NewLineOnAttributes = true;

                XmlWriter xmlPlaylist;
                xmlPlaylist = XmlWriter.Create(Metal.Config.Paths.UserFolder + "QueueList.xml", xmlSettings);
                ListDataSet.WriteXml(xmlPlaylist);
                xmlPlaylist.Close();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Subscribe to events defined in the view
        /// </summary>
        private void SubscribeToViewEvents()
        {
            view.MaskLoad += new EventHandler(this.OnMaskLoad);
            view.MaskClose += new EventHandler(this.OnMaskClose);
            view.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.OnControlAdded);
        }

        /// <summary>
        /// Load last playlist
        /// </summary>
        private void LoadLastQueue()
        {
            try
            {
                // Load list data set
                ListDataSet = new DataSet();

                // Get the dataset with all neccessary columns (loaded from theme xml)
                ListDataSet = View.ListDataSet;

                // Load last list in our dataset
                ListDataSet.ReadXml(Metal.Config.Paths.UserFolder + "QueueList.xml");

                // Update
                View.ListDataSet = ListDataSet;
            }
            catch
            {
                // We can ignore it I think...
            }
        }

        /// <summary>
        /// Play selected file
        /// </summary>
        private void ListDoubleClick()
        {
            try
            {
                Core.Player.Playback.Instance.Open(QueueController.view.ListSelectedRow.Cells[1].Value.ToString());
                Core.Player.Playback.Instance.Play();

                QueueLogic.Instance.RemoveFromQueue();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion

        #region Mask events

        /// <summary>
        /// This method is called when the mask is loaded.
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event arguments</param>
        private void OnMaskLoad(object sender, EventArgs e)
        {
            try
            {
                this.LoadLastQueue();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This method is called when the mask is closed.
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event arguments</param>
        private void OnMaskClose(object sender, EventArgs e)
        {
            try
            {
                SaveCurrentPlaylist();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This method is called when a control is added on the mask
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event arguments</param>
        private void OnControlAdded(object sender, System.Windows.Forms.ControlEventArgs e)
        {
            try
            {
                if (e.Control.GetType() == typeof(Gui.Controls.MetalList))
                {
                    e.Control.DoubleClick += new EventHandler(this.OnListDoubleClick);

                    if ((e.Control as Gui.Controls.MetalList).ContextMenuStrip != null)
                    {
                        (e.Control as Gui.Controls.MetalList).ContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(this.OnContextMenuClick);
                    }
                    else if (e.Control.GetType() == typeof(Gui.Controls.MetalPanel))
                    {
                        e.Control.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.OnControlAdded);
                    }
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion

        #region Controls events

        /// <summary>
        /// This event occurs on DoubleClick event
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event args</param>
        private void OnListDoubleClick(object sender, EventArgs e)
        {
            try
            {
                Type thisType = typeof(QueueController);
                MethodInfo theMethod = thisType.GetMethod(((Gui.Controls.MetalList)sender).Name + "DoubleClick", BindingFlags.NonPublic | BindingFlags.Instance);
                if (theMethod != null)
                {
                    theMethod.Invoke(this, null);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// This event occurs when the user clicks on menu
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="e">ToolStripItem event args</param>
        private void OnContextMenuClick(object sender, ToolStripItemClickedEventArgs e)
        {
            try
            {
                string methodName = e.ClickedItem.Tag.ToString();

                // Call the method via reflection
                Type thisType = typeof(QueueLogic);
                System.Reflection.MethodInfo theMethod = thisType.GetMethod(methodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                if (theMethod != null)
                {
                    theMethod.Invoke(QueueLogic.Instance, null);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        #endregion
    }
}
